<?php

namespace App\Jobs\Finance;

use App\Models\Finance\Wages;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Database\Query\JoinClause;
use App\Package\Finance\RegulationHandler;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

/**
 * 每月生成薪资报表任务
 *
 * Date: 2018/6/13
 * @author George
 * @package App\Jobs\Finance
 */
class MonthlySalaryGenerator implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

	/**
	 * 定义保存规则计算器实例
	 *
	 * @var RegulationHandler
	 * Date: 2018/6/13
	 * @author George
	 */
    protected $handler;

	/**
	 * MonthlySalaryGenerator constructor.
	 */
    public function __construct()
    {

    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
    	$users = $this->users();
    	$users = $this->fields($users);
    	foreach ($users as $user) {
    		// 创建薪资数据
    		$wages = Wages::create($user);
    		$this->handler = new RegulationHandler($wages);
    		// 计算并更新薪资数据
    		$this->handler->calculate();
		}
    }

	/**
	 * 根据薪资方案获取薪资字段
	 *
	 * Date: 2018/6/13
	 * @author George
	 * @param Collection $users
	 * @return Collection
	 */
    private function fields(Collection $users)
	{
		return $users->map(function ($user) {
			$fields = Cache::remember("company:{$user->company_id}:fields", 20, function () use ($user) {
				return DB::table('fields')->select(['id', 'company_id', 'pattern_id', 'name', 'salary', 'tax'])->where([
					['company_id', '=', $user->company_id],
					['pattern_id', '=', $user->pattern_id]
				])->get();
			});
			$user->custom_fields = $fields;
			return (array) $user;
		});
	}

	/**
	 * 获取需要计算薪资的用户
	 *
	 * Date: 2018/6/12
	 * @author George
	 * @return Collection
	 */
	private function users()
	{
		$year = date('Y');
		$month = date('m', strtotime('-1 month'));
		$users = DB::table('salaries')->select([
			'users.id as user_id', 'users.name as user_name',
			'users.company_id', 'users.identification',
			'company_user_pivot.hiredate_at',
			'company_user_pivot.expiry',
			'departments.name as department_name',
			'positions.name as position_name',
			'salaries.pattern_id', 'patterns.name as pattern_name',
			'monthly_attendance_reports.days as attendance_days','monthly_attendance_reports.holidays',
			'monthly_attendance_reports.year','monthly_attendance_reports.month'
		])
			->leftJoin('users', 'salaries.user_id', '=', 'users.id')
			->leftJoin('company_user_pivot', function ($join) {
				/**
				 * @var JoinClause $join
				 */
				$join->on('salaries.user_id', '=', 'company_user_pivot.user_id')
					->whereNull('company_user_pivot.departure_at');
			})
			->leftJoin('departments', 'users.department_id', '=', 'departments.id')
			->leftJoin('positions', 'users.position_id', '=', 'positions.id')
			->leftJoin('patterns', 'salaries.pattern_id', '=', 'patterns.id')
			->leftJoin('monthly_attendance_reports', function ($join) use ($year, $month) {
				/**
				 * @var JoinClause $join
				 */
				$join->on('salaries.user_id', '=', 'monthly_attendance_reports.user_id')
					->where([
						['year', '=', $year],
						['month', '=', $month],
					]);
			})->get();

		return $users;
    }
}
